<?php

namespace App\Http\Controllers\Api;

use App\Http\Resources\UserResource;
use App\Models\UserThirdPartyBind;
use Illuminate\Http\Request;
use App\Http\Requests\UserRequest;
use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;
use GuzzleHttp\Client;
use App\Models\User;
use App\Models\Role;
use Illuminate\Support\Facades\Hash;


class AuthenticateController extends Controller
{

    /**
     * 账号密码登录，获取token
     * 
     * @param UserRequest $request
     * @return array
     */
    public function login(Request $request)
    {
        $data = [
            'grant_type' => 'password',
            'client_id' => $request->get('client_id', config('oauth.client_id')),
            'client_secret' => $request->get('client_secret', config('oauth.client_secret')),
            'username' => $request->username,
            'password' => $request->password,
            'scope' => '',
        ];
        $url = url('/') . "/oauth/token";
        return $this->requestOAuthServer("post", $url, ['form_params' => $data]);
    }

    /**
     * 刷新token
     *
     * @param Request $request
     * @return array
     */
    public function refreshToken(Request $request)
    {
        $data = [
            'grant_type' => 'refresh_token',
            'client_id' => $request->get('client_id', config('oauth.client_id')),
            'client_secret' => $request->get('client_secret', config('oauth.client_secret')),
            'refresh_token' => $request->refresh_token,
            'scope' => '',
        ];
        $url = url('/') . "/oauth/token";
        //结果码-1001，刷新token失败，这里前端需要进行登录操作了。
        return $this->requestOAuthServer("post", $url, ['form_params' => $data], -1001);
    }

    /**
     * 退出，删除access_token
     *
     * @param Request $request
     * @return array
     */
    public function logout(Request $request)
    {
//        dd(\Auth::user());
        $result = \Auth::user()->tokens()->delete();
        if ($result) {
            return normalize(0, "OK", []);
        } else {
            return normalize("删除 token 失败");
        }
    }

    public function register(UserRequest $request)
    {
        $result = (new UserRepository())->create($request);
        if ($result['ret'] !== 0)
        {
            return $result;
        }
        //注册成功后直接登录
        $request->query->set('username', $request->email);
        return $this->login($request);
    }

    private function requestOAuthServer($method, $url, array $options = [], $failureCode = -1)
    {
        try
        {
            $client = new Client();
            $response = call_user_func_array([$client, $method], [$url, $options]);
            $result = json_decode((string)$response->getBody(), true);
            return normalize(0, "OK", $result);
        }
        catch (\Exception $e)
        {
            $result = json_decode((string)$e->getResponse()->getBody(), true);
            return normalize($failureCode, get_class($e) . ': ' . $result['message'], request()->all());
        }
    }

    /**
     * 通过微信小程序登录
     *
     * @param Request $request
     * @return array
     */
    public function loginByWeixinMiniProgram(Request $request)
    {
        $code = $request->code;
        if (!$code)
        {
            return api("缺少code");
        }
        $platform = UserThirdPartyBind::PLATFORM_WEIXIN_OPEN;
        $miniApp = \EasyWechat::miniProgram();
        $session = $miniApp->auth->session($code);
        \Log::info(__METHOD__, (array)$session);
        $thirdPartyBind = UserThirdPartyBind::platformWeixinOpen()->where("openid", $session->openid)->whereNotNull('uid')->first();
        if ($thirdPartyBind && ($user = $thirdPartyBind->user)) {
            //用户经存在
            return $this->doLogin($user, __METHOD__);
        } else {
            //不存在，返回注册 ret
            $thirdPartyBind = UserThirdPartyBind::firstOrcreate([
                'platform' => $platform,
                'openid' => $session->openid,
                'unionid' => $session->unionid ?? null,
            ]);
            $thirdPartyBind->update(['session_key' => $session->session_key]);

            return api(RET_BIND_ACCOUNT, '绑定已有账号，或注册新账号', ['third_party_bind_id' => $thirdPartyBind->id]);
        }

    }

    /**
     * 通过微信小程序注册
     *
     * @param Request $request
     * @return array
     */
    public function registerByWeixinMiniProgram(Request $request)
    {
        $iv = $request->iv;
        if (!$iv) {
            return api("缺少 iv");
        }
        $encryptedData = $request->encryptedData;
        if (!$encryptedData) {
            return api("缺少 encryptedData");
        }
        $thirdPartyBind = UserThirdPartyBind::findOrFail($request->third_party_bind_id);
        $miniApp = \EasyWechat::miniProgram();
        $decryptedData = $miniApp->encryptor->decryptData($thirdPartyBind['session_key'], $iv, $encryptedData);

        //创建用户
        $user = User::query()->create([
            'name' => $decryptedData['nickName'],
            'gender' => $decryptedData['gender'],
            'register_source' => $thirdPartyBind->platform,
            'avatar' => $decryptedData['avatarUrl'],
        ]);
        //更新绑定
        $thirdPartyBind->update([
            'uid' => $user->id,
            'nickname' => $user->name,
            'info' => $decryptedData,
        ]);

        return $this->doLogin($user, __METHOD__);

    }

    /**
     * 通过账号密码登录
     *
     * @param Request $request
     * @return array
     */
    public function loginByAccountPassword(Request $request)
    {
        $account = $request->account;
        $password = $request->password;
        if (!$account || !$password)
        {
            return api("缺少账号或密码");
        }
        if (filter_var($account, FILTER_VALIDATE_EMAIL)) {
            $user = User::query()->where('email', $account)->first();
        } else {
            return api("错误的账号类型，只支持邮箱");
        }
        if (!$user) {
            return api("账号不存在");
        }
        if (!Hash::check($password, $user->password)) {
            return api("密码错误");
        }
        return $this->doLogin($user, __METHOD__);

    }

    /**
     * 通过账号密码注册
     *
     * @param Request $request
     * @return array
     */
    public function registerByAccountPassword(Request $request)
    {
        $account = $request->account;
        $password = $request->password;
        if (!$account || !$password)
        {
            return api("缺少账号或密码");
        }
        $registerSource = '';
        if (filter_var($account, FILTER_VALIDATE_EMAIL)) {
            $user = User::query()->where('email', $account)->first();
            $registerSource = User::REGISTER_SOURCE_EMAIL;
        } else {
            return api("错误的账号类型，只支持邮箱");
        }
        if ($user) {
            return api("账号已经存在");
        }
        $userData = [
            'username' => substr($account, 0, 8),
            'email' => $account,
            'password' => Hash::make($password),
            'register_source' => $registerSource
        ];
        $user = User::query()->create($userData);
        return $this->doLogin($user, __METHOD__);

    }

    private function doLogin(User $user, $caller = __METHOD__)
    {
        $tokenResult = $user->createToken($caller);

        //触发登录事件，方便后续更多操作，添加更多事件监听者即可
//        $user->login_ip = request()->ip();
//        event(new UserLogin($user));

        $log = sprintf(
            "%s, params: %s, user: %s, access_token: %s",
            $caller, json_encode(request()->all(), 336), $user->id, $tokenResult->accessToken
        );
        \Log::info($log);

        //不返回过多敏感信息
        return api(RET_OK, MSG_OK, [
            'id' => $user->id,
            'key' => $user->key,
            'username' => $user->username,
            'auth' => [
                'access_token' => $tokenResult->accessToken,
                'expires_at' => (string)$tokenResult->token->expires_at,
            ],
        ]);
    }

}
